package com.typhoon.spring_jdbctemplate.dao;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

import com.typhoon.spring_jdbctemplate.exception.DaoRuntimeException;
import com.typhoon.spring_jdbctemplate.util.CollectionUtils;
import com.typhoon.spring_jdbctemplate.util.RegUtil;
import com.typhoon.spring_jdbctemplate.vo.QueryResultVO;

public class BaseDao {
	protected static final String select = "select ";
	protected static final String from = " from ";
	protected static final String where = " where ";
	protected static final String and = " and ";
	protected static final String orderBy = " order by ";
	protected static final String oneEqOne = " 1=1 ";
	protected static final String count = " count ";
	protected static final String sum = " sum ";
	protected static final String allSymbol = "(*) ";
	protected static final String seqId = "seqId";
	protected static final String star = " * ";
	
	protected static final String limitOne = " limit 1";
	
	protected static Logger log = LoggerFactory.getLogger(BaseDao.class);

	/**
	 * 保存单条记录
	 * 
	 * @author Typhoon
	 * @date 2017-10-17 17:19 Tuesday
	 * @since V2.0
	 * @param jdbcTemplate
	 * @param tableName
	 * @param obj
	 */
	protected <T> void addObj(JdbcOperations jdbcTemplate, String tableName, T obj) {
		StringBuilder sbField = new StringBuilder();
		StringBuilder sbArgs = new StringBuilder();
		List<Object> args = new ArrayList<>();

		sbField.append(" ( ");
		sbArgs.append(" ( ");
		Field[] fields = obj.getClass().getDeclaredFields();
		if ((fields != null) && (fields.length > 0)) {
			String name = "";
			Object value = null;
			for (int i = 0; i < fields.length; i++) {
				name = fields[i].getName();
				if (name.equalsIgnoreCase("serialversionuid")) {//如果是序列化编号就过滤
					continue;
				}
				if ("seqId".equalsIgnoreCase(name)) {
					continue;
				}
				value = RegUtil.getProperty(obj, name);
				if (null == value) {
					continue;
				}
				sbArgs.append("? ");
				sbField.append(name);
				if (i < fields.length - 1) {
					sbField.append(", ");
					sbArgs.append(", ");
				}
				args.add(value);
			}
		}
		if (sbField.toString().trim().endsWith(",")) {
			sbField = new StringBuilder(sbField.substring(0, sbField.lastIndexOf(",")));
		}
		if (sbArgs.toString().trim().endsWith(",")) {
			sbArgs = new StringBuilder(sbArgs.substring(0, sbArgs.lastIndexOf(",")));
		}
		sbField.append(" ) ");
		sbArgs.append(" ) ");
		StringBuilder sql = new StringBuilder();
		sql.append("insert into ").append(tableName).append(" ");
		sql.append(sbField).append(" values ").append(sbArgs);

		if (!"actionLog".equals(tableName)) {
			log.debug(sql.toString() + args.toString());
		}
		jdbcTemplate.update(sql.toString(), args.toArray());
	}

	/**
	 * insert ignore
	 *
	 * @param jdbcTemplate
	 * @param tableName
	 * @param obj
	 */
	protected <T> void addObjIgnore(JdbcOperations jdbcTemplate, String tableName, T obj) {
		StringBuilder sbField = new StringBuilder();
		StringBuilder sbArgs = new StringBuilder();
		List<Object> args = new ArrayList<Object>();

		sbField.append(" ( ");
		sbArgs.append(" ( ");
		Field[] fields = obj.getClass().getDeclaredFields();
		if ((fields != null) && (fields.length > 0)) {
			String name = "";
			Object value = null;
			for (int i = 0; i < fields.length; i++) {
				name = fields[i].getName();
				if (!name.toLowerCase().equals("serialversionuid")) {
					value = RegUtil.getProperty(obj, name);

					if (value != null) {
						if (!"seqId".equalsIgnoreCase(name)) {
							sbField.append(name);
							if (i < fields.length - 1)
								sbField.append(", ");

							sbArgs.append("? ");
							if (i < fields.length - 1)
								sbArgs.append(", ");
							args.add(value);
						}
					}
				}
			}
		}
		if (sbField.toString().trim().endsWith(",")) {
			sbField = new StringBuilder(sbField.substring(0, sbField.lastIndexOf(",")));
		}
		if (sbArgs.toString().trim().endsWith(",")) {
			sbArgs = new StringBuilder(sbArgs.substring(0, sbArgs.lastIndexOf(",")));
		}
		sbField.append(" ) ");
		sbArgs.append(" ) ");
		StringBuilder sql = new StringBuilder();
		sql.append("insert ignore into ").append(tableName).append(" ");
		sql.append(sbField).append(" values ").append(sbArgs);

		if (!"actionLog".equals(tableName)) {
			log.debug(sql.toString() + args.toString());
		}

		jdbcTemplate.update(sql.toString(), args.toArray());
	}

	protected int deleteByPrimaryKey(JdbcTemplate jdbcTemplate, String tableName, String primaryKey, Object... primaryValue) {
		if (jdbcTemplate == null || StringUtils.isBlank(tableName) || StringUtils.isBlank(primaryKey)) {
			return 0;
		}
		StringBuilder sql1 = new StringBuilder();
		List args = new ArrayList();
		sql1.append("delete from ").append(tableName).append(" where 1= 1 ");
		String[] keys = primaryKey.split(",");
		for (int i = 0; i < keys.length; i++) {
			sql1.append(" and ").append(keys[i]).append("=").append("?");
			args.add(primaryValue[i]);
		}
		if (sql1.indexOf("?") > 0) {
			return jdbcTemplate.update(sql1.toString(), args.toArray());
		} else {
			return 0;
		}
	}

	protected int update(final JdbcTemplate jdbcTemplate, String tableName, Map<String, Object> dataMap, String primaryKey, Object... primaryValue) {

		if (jdbcTemplate == null || dataMap == null || dataMap.size() == 0 || StringUtils.isBlank(tableName) || StringUtils.isBlank(primaryKey)) {
			return 0;
		}
		StringBuilder sql1 = new StringBuilder();
		List args = new ArrayList();

		sql1.append("update ").append(tableName).append(" set ");

		Set<String> keySet = dataMap.keySet();
		for (Iterator<String> it = keySet.iterator(); it.hasNext();) {
			String key = it.next();
			Object value = dataMap.get(key);
			if (value == null) {
				continue;
			} else {
				sql1.append(key).append("=");
				sql1.append("?, ");
				args.add(value);
				// sql1.append("'").append(StringUtil.encodeSQL(value.toString())).append("',
				// ");
			}
		}
		sql1 = new StringBuilder(sql1.subSequence(0, sql1.lastIndexOf(",")));
		sql1.append(" where 1=1");
		String[] keys = primaryKey.split(",");
		for (int i = 0; i < keys.length; i++) {
			sql1.append(" and ").append(keys[i]).append("=").append("?");
			args.add(primaryValue[i]);
		}
		if (sql1.indexOf("?") > 0) {
			return jdbcTemplate.update(sql1.toString(), args.toArray());
		} else {
			return 0;
		}

	}

	protected <T> T addObjForKey(final JdbcOperations jdbcTemplate, String tableName, T obj, String primaryKey) {
		StringBuilder sbField = new StringBuilder();
		StringBuilder sbArgs = new StringBuilder();
		List<Object> args = new ArrayList<>();

		sbField.append(" ( ");
		sbArgs.append(" ( ");
		Field[] fields = obj.getClass().getDeclaredFields();
		if ((fields != null) && (fields.length > 0)) {
			String name = "";
			Object value = null;
			for (int i = 0; i < fields.length; i++) {
				name = fields[i].getName();
				if (!name.toLowerCase().equals("serialversionuid")) {
					value = RegUtil.getProperty(obj, name);
					if (value != null) {
						if (!"seqId".equals(name)) {
							sbField.append(name);
							if (i < fields.length - 1)
								sbField.append(", ");

							sbArgs.append("? ");
							if (i < fields.length - 1)
								sbArgs.append(", ");
							args.add(value);
						}
					}
				}
			}
		}
		if (sbField.toString().trim().endsWith(",")) {
			sbField = new StringBuilder(sbField.substring(0, sbField.lastIndexOf(",")));
		}
		if (sbArgs.toString().trim().endsWith(",")) {
			sbArgs = new StringBuilder(sbArgs.substring(0, sbArgs.lastIndexOf(",")));
		}
		sbField.append(" ) ");
		sbArgs.append(" ) ");
		StringBuilder sql = new StringBuilder();
		sql.append("insert into ").append(tableName).append(" ");
		sql.append(sbField).append(" values ").append(sbArgs);

		final String finalsql = sql.toString();
		final List<Object> list = args;

		KeyHolder keyHolder = new GeneratedKeyHolder();

		jdbcTemplate.update(new PreparedStatementCreator() {
			public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
				PreparedStatement pst = con.prepareStatement(finalsql, Statement.RETURN_GENERATED_KEYS);
				if (null != list && !list.isEmpty()) {
					for (int i = 0; i < list.size(); i++) {
						pst.setObject(i + 1, list.get(i));
					}
				}
				return pst;
			}
		}, keyHolder);
		if (StringUtils.isBlank(primaryKey)) {
			primaryKey = "seqId";
		}
		RegUtil.setProperty(obj, primaryKey, keyHolder.getKey().longValue());
		return obj;
	}

	protected <T> List<T> queryList(JdbcOperations jdbcTemplate, Class<T> clazz, String sql, Object[] args) {
		return jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(clazz),args);
	}

	protected Integer queryCount(JdbcOperations jdbcTemplate, String sql, Object[] args) {
		return jdbcTemplate.queryForObject(sql, Integer.class, args);
	}

	protected <T> List<T> convertColToObj(List<Map<String, Object>> mapList, Class<T> clazz) {
		List rs = null;
		if ((mapList != null) && (!mapList.isEmpty())) {
			try {
				rs = new ArrayList();

				for (Map map : mapList) {
					if (RegUtil.isPlainClass(clazz)) {
						Object value = map.values().iterator().next();
						if (value != null) {
							Object o = RegUtil.convertValue(clazz, String.valueOf(value));
							if (o != null) {
								Object obj = o;
								rs.add(obj);
							}
						}
					} else {
						Object obj = clazz.newInstance();
						Set<String> keys = map.keySet();
						for (String key : keys) {
							Object value = map.get(key);
							if (value != null) {
								RegUtil.setProperty(obj, String.valueOf(key), value);
							}
						}
						rs.add(obj);
					}
				}
			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}
		}
		return rs;
	}

	private static Integer getStartOfPage(Integer pageNo, Integer pageSize, Integer totalCount) {
		int totalPage = totalCount.intValue() % pageSize.intValue() > 0 ? totalCount.intValue() / pageSize.intValue() + 1
				: totalCount.intValue() / pageSize.intValue();
		if (pageNo.intValue() < 1)
			return Integer.valueOf(0);
		// if (pageNo.intValue() > totalPage)
		// return Integer.valueOf((totalPage - 1) * pageSize.intValue());
		return Integer.valueOf((pageNo.intValue() - 1) * pageSize.intValue());
	}

	protected static String removeSelect(String hql) {
		int beginPos = hql.toLowerCase().indexOf("from");
		return hql.substring(beginPos);
	}

	protected static String removeOrders(String hql) {
		Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", 2);
		Matcher m = p.matcher(hql);
		StringBuffer sb = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(sb, "");
		}
		m.appendTail(sb);
		return sb.toString();
	}

	protected <T> QueryResultVO<T> pagedQuery(JdbcOperations jdbcTemplate, Class<T> clazz, String sql, Object[] values, QueryResultVO<T> query) {
		Integer totalCount = count(jdbcTemplate, sql, values);
		if (totalCount < 1) {
			query.setRowCount(0);
			query.setPageIndex(0);
			query.setList(new ArrayList<T>());
		} else {
			StringBuilder sb = new StringBuilder(sql);
			sb.append(" limit ").append(getStartOfPage(query.getPageIndex(), query.getPageSize(), totalCount));
			sb.append(",").append(query.getPageSize());
			log.debug(sb.toString() + Arrays.toString(values));
			query.setRowCount(totalCount);
			int totalPage = totalCount % query.getPageSize() > 0 ? totalCount / query.getPageSize() + 1 : totalCount / query.getPageSize();
			if (query.getPageIndex() > totalPage) {
				query.setList(new ArrayList<T>());
			} else {
				List<T> list = queryList(jdbcTemplate, clazz, sb.toString(), values);

				query.setList(list);
			}

			query.setPageCount(totalPage);
			if (query.getPageIndex() == totalPage) {
				query.setLastPage(true);
			}
		}
		return query;
	}

	protected Integer count(JdbcOperations jdbcTemplate, String sql, Object[] values) {
		String countQueryString = " select count(*) " + removeSelect(removeOrders(sql));
		Integer totalCount = queryCount(jdbcTemplate, countQueryString, values);
		return totalCount;
	}

	protected int executeSQL(JdbcOperations jdbcTemplate, String sql) {
		if ((sql != null) && (!"".equals(sql))) {
			log.debug(sql.toString());
			return jdbcTemplate.update(sql);
		}
		return 0;
	}

	protected int executeSQL(JdbcOperations jdbcTemplate, String sql, Object[] args) {
		if ((sql != null) && (!"".equals(sql))) {
			log.debug(sql.toString() + Arrays.toString(args));
			return jdbcTemplate.update(sql, args);
		}
		return 0;
	}

	protected <T> T querySingleObj(JdbcOperations jdbcTemplate, Class<T> clazz, String sql, Object[] args) {
		if(!sql.toLowerCase().endsWith(limitOne)) {
			sql = sql + limitOne;
		}
		List<T> list = queryList(jdbcTemplate, clazz, sql, args);
		if ((list != null) && (list.size() > 0)) {
			return list.get(0);
		}
		return null;
	}

	protected <T> void replaceObj(JdbcOperations jdbcTemplate, String tableName, T obj) {
		StringBuilder sbField = new StringBuilder();
		StringBuilder sbArgs = new StringBuilder();
		List args = new ArrayList();

		sbField.append(" ( ");
		sbArgs.append(" ( ");
		Field[] fields = obj.getClass().getDeclaredFields();
		if ((fields != null) && (fields.length > 0)) {
			String name = "";
			Object value = null;
			for (int i = 0; i < fields.length; i++) {
				name = fields[i].getName();
				if (!name.toLowerCase().equals("serialversionuid")) {
					value = RegUtil.getProperty(obj, name);

					sbField.append(name);
					if (i < fields.length - 1)
						sbField.append(", ");

					sbArgs.append("? ");
					if (i < fields.length - 1)
						sbArgs.append(", ");
					args.add(value);
				}
			}
		}
		if (sbField.toString().trim().endsWith(",")) {
			sbField = new StringBuilder(sbField.substring(0, sbField.lastIndexOf(",")));
		}
		if (sbArgs.toString().trim().endsWith(",")) {
			sbArgs = new StringBuilder(sbArgs.substring(0, sbArgs.lastIndexOf(",")));
		}
		sbField.append(" ) ");
		sbArgs.append(" ) ");
		StringBuilder sql = new StringBuilder();
		sql.append("replace into ").append(tableName).append(" ");
		sql.append(sbField).append(" values ").append(sbArgs);

		jdbcTemplate.update(sql.toString(), args.toArray());
	}

	/**
	 * 根据主键修改信息
	 * 
	 * @author Typhoon
	 * @date 2017-05-15
	 * @since V2.0
	 * @description
	 *              <ul>
	 *              <li>如果传了主键就根据传入的主键更新</li>
	 *              <li>根据传入的对象,只对非null列更新</li>
	 *              </ul>
	 * @param jdbcTemplate
	 * @param t
	 * @param tableName
	 * @param primaryKey
	 * @return
	 */
	protected <T> int updateByPrimaryKey(JdbcOperations jdbcTemplate, T t, String tableName, String primaryKey) {
		StringBuilder sql = new StringBuilder();
		List<Object> args = new ArrayList<>();

		sql.append(" UPDATE  ").append(tableName).append(" SET ");

		Field[] fields = t.getClass().getDeclaredFields();
		if (null == fields || 0 >= fields.length) {
			throw new DaoRuntimeException(" there is not field ");
		}
		String name = "";
		Object value = null;
		for (int i = 0, length = fields.length; i < length; i++) {
			name = fields[i].getName();
			if ("serialversionuid".equalsIgnoreCase(name)) {// 序列化id字段跳过
				continue;
			}
			if ("id".equalsIgnoreCase(name)) {// id用来作为条件修改
				continue;
			}
			value = RegUtil.getProperty(t, name);
			if (null == value) {
				continue;
			}
			sql.append(name).append("= ?,");
			args.add(value);
		}
		if (null == args || args.isEmpty()) {
			throw new DaoRuntimeException("there is no field to update");
		}
		if (sql.toString().trim().endsWith(",")) {
			sql = new StringBuilder(sql.substring(0, sql.lastIndexOf(",")));
		}
		sql.append(where);
		if (null == primaryKey || 0 >= primaryKey.length()) {
			primaryKey = "id";
		}
		sql.append(primaryKey).append(" = ?  ");
		args.add(RegUtil.getProperty(t, primaryKey));
		log.debug("sql-{},params-{}", sql.toString(), args.toString());
		return jdbcTemplate.update(sql.toString(), args.toArray());
	}

	protected <T> int updateByPrimaryKey(JdbcOperations jdbcTemplate, T t, String tableName) {
		return this.updateByPrimaryKey(jdbcTemplate, t, tableName, null);
	}

	/**
	 * 根据主键查询信息
	 * 
	 * @author Typhoon
	 * @date 2017-05-16 14:44
	 * @since V2.0
	 * @description
	 *              <p>
	 *              如果指定主键为空,默认使用id查询
	 *              </p>
	 * @param jdbcTemplate
	 * @param tableName
	 * @param primaryKey
	 * @param value
	 * @param clazz
	 * @return T
	 */
	protected <T> T queryByPrimaryKey(JdbcOperations jdbcTemplate, String tableName, String primaryKey, Object value, Class<T> clazz) {
		StringBuilder sqlBuilder = new StringBuilder();
		sqlBuilder.append(select);
		sqlBuilder.append(star);
		sqlBuilder.append(from);
		sqlBuilder.append(tableName);
		if (null == primaryKey || 0 >= primaryKey.length()) {
			primaryKey = "id";
		}
		sqlBuilder.append(where);
		sqlBuilder.append(primaryKey);
		sqlBuilder.append("  = ? limit 1 ");
		log.debug("querySql-{}", sqlBuilder.toString());
		List<T> list = jdbcTemplate.query(sqlBuilder.toString(), BeanPropertyRowMapper.newInstance(clazz), value);
		if(null == list || list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

	protected <T> T queryByPrimaryKey(JdbcOperations jdbcTemplate, String tableName, Object value, Class<T> clazz) {
		return this.queryByPrimaryKey(jdbcTemplate, tableName, null, value, clazz);
	}

	/**
	 * 简化版单表查询
	 * 
	 * @author Typhoon
	 * @date 2017-05-17 15:46
	 * @param jdbcTemplate
	 * @param tableName
	 * @param param
	 * @param clazz
	 * @return
	 */
	protected <T> List<T> list(JdbcOperations jdbcTemplate, String tableName, Object param, Class<T> clazz) {
		StringBuilder sql = new StringBuilder();
		sql.append(select).append(star).append(from).append(tableName).append(where).append(oneEqOne);
		SqlAssembleResult joinResult = assembleQuery(param);
		if (null == joinResult || StringUtils.isEmpty(joinResult.getJoinSql()) || CollectionUtils.isEmpty(joinResult.getArgs())) {
			log.debug("querySql-{}", sql.toString());
			return jdbcTemplate.query(sql.toString(), BeanPropertyRowMapper.newInstance(clazz));
		}
		sql.append(joinResult.getJoinSql());
		log.debug("querySql-{}", sql.toString());
		return jdbcTemplate.query(sql.toString(), BeanPropertyRowMapper.newInstance(clazz),joinResult.getArgs().toArray());
	}

	/**
	 * 简化版单表数量查询
	 * 
	 * @author Typhoon
	 * @date 2017-05-17 15:42
	 * @since V2.0
	 * @description
	 *              <ul>
	 *              <li>只需传来表名和参数</li>
	 *              <li>避免了上层拼接不可靠sql引起异常</li>
	 *              </ul>
	 * @param jdbcTemplate
	 * @param tableName
	 * @param param
	 * @return
	 */
	protected long count(JdbcOperations jdbcTemplate, String tableName, Object param) {
		StringBuilder sql = new StringBuilder();
		sql.append(select).append(count).append(" (1) ").append(from).append(tableName).append(where).append(oneEqOne);
		SqlAssembleResult joinResult = assembleQuery(param);
		if (null == joinResult || StringUtils.isEmpty(joinResult.getJoinSql()) || CollectionUtils.isEmpty(joinResult.getArgs())) {
			log.debug("querySql-{}", sql.toString());
			return this.queryCount(jdbcTemplate, sql.toString(), null);
		}
		sql.append(joinResult.getJoinSql());
		log.debug("querySql-{}", sql.toString());
		return this.queryCount(jdbcTemplate, sql.toString(), joinResult.getArgs().toArray());
	}

	/**
	 * 组装查询条件
	 * 
	 * @author Typhoon
	 * @date 2017-05-17 15:45
	 * @since V2.0
	 * @param param
	 * @return
	 */
	private SqlAssembleResult assembleQuery(Object param) {
		if (null == param) {
			return null;
		}
		StringBuilder joinSql = new StringBuilder();
		List<Object> args = new ArrayList<>();
		if (param instanceof Map) {// map实例

			Map map = (Map) param;
			if (null == map || map.isEmpty()) {
				return null;
			}
			Object value = null;
			for (Object key : map.keySet()) {
				value = map.get(key);
				if (null == value) {
					continue;
				}
				joinSql.append(and).append(key.toString()).append(" = ? ");
				args.add(value);
			}

		} else {
			Field[] fields = param.getClass().getDeclaredFields();
			if (null == fields || fields.length <= 0) {
				return null;
			}
			String name = "";
			Object value = null;
			for (int i = 0, length = fields.length; i < length; i++) {
				name = fields[i].getName();
				if ("serialversionuid".equalsIgnoreCase(name)) {// 序列化id字段跳过
					continue;
				}
				value = RegUtil.getProperty(param, name);
				if (null == value) {
					continue;
				}
				joinSql.append(and).append(name).append(" = ? ");
				args.add(value);
			}
		}
		if (joinSql.length() <= 0 || args.isEmpty()) {
			return null;
		}
		return new SqlAssembleResult(joinSql.toString(), args);
	}

	/**
	 * sql中间态拼接结果
	 * 
	 * @author Typhoon
	 * @date 2017-05-17 14:52
	 * @since V2.0
	 * @description
	 *              <p>
	 *              限于java只能有单个返回值,而sql中间态拼接结果中包含sql和参数列表,从而写了一个内部封装类
	 *              </p>
	 */
	static class SqlAssembleResult {

		/**
		 * 拼接的中间结果
		 */
		private String joinSql;

		/**
		 * 参数列表
		 */
		private List<Object> args;

		public SqlAssembleResult() {
		}

		public SqlAssembleResult(String joinSql, List<Object> args) {
			super();
			this.joinSql = joinSql;
			this.args = args;
		}

		public String getJoinSql() {
			return joinSql;
		}

		public void setJoinSql(String joinSql) {
			this.joinSql = joinSql;
		}

		public List<Object> getArgs() {
			return args;
		}

		public void setArgs(List<Object> args) {
			this.args = args;
		}

	}

	/**
	 * 简化版根据条件查询单个信息
	 * 
	 * @author Typhoon
	 * @date 2017-05-17 16:15
	 * @since V2.0
	 * @param jdbcTemplate
	 * @param tableName
	 * @param param
	 * @param clazz
	 * @return
	 */
	protected <T> T get(JdbcOperations jdbcTemplate, String tableName, Object param, Class<T> clazz) {
		StringBuilder sql = new StringBuilder();
		sql.append(select).append(star).append(from).append(tableName).append(where).append(oneEqOne);
		SqlAssembleResult joinResult = assembleQuery(param);
		Object[] args = null;
		if (null != joinResult && CollectionUtils.isNotEmpty(joinResult.getArgs()) && StringUtils.isNotEmpty(joinResult.getJoinSql())) {
			sql.append(joinResult.getJoinSql());
			args = joinResult.getArgs().toArray();
		}
		sql.append(" limit 1  ");
		log.debug("querySql-{}", sql.toString());
		List<T> list = jdbcTemplate.query(sql.toString(), args, BeanPropertyRowMapper.newInstance(clazz));
		if(null == list || list.isEmpty()) {
			return null;
		}
		return list.get(0);
	}

}
